package org.apache.ibatis.reflection;

import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;

import org.apache.ibatis.domain.blog.Blog;
import org.apache.ibatis.reflection.invoker.Invoker;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

import com.wxg.mybatisstudy.bean.Student;

/**
 * MetaClass My Test
 * @author wxg
 *
 */
public class MetaClassMYT {

	
	@Test
	public void test007(){
		ReflectorFactory rf = new DefaultReflectorFactory();
		MetaClass mc = MetaClass.forClass(Student.class, rf);
		
		Assert.assertEquals("[yuwen, sex, name, classRoom, id, age]", Arrays.toString( mc.getGetterNames() ));
	}
	
	/**
	 * useCamelCaseMapping
	 */
	@Test
	public void test006useCamelCaseMapping(){
		ReflectorFactory rf = new DefaultReflectorFactory();
		MetaClass mc = MetaClass.forClass(Student.class, rf);
		
		Assert.assertEquals("classRoom", mc.findProperty("class_room", true));
	}
	
	
	/**
	 * findProperty
	 */
	@Test
	public void test005findProperty(){
		Assert.assertEquals("id", metaclass.findProperty("id"));
		Assert.assertNull( metaclass.findProperty("id2") );
		
		ReflectorFactory rf = new DefaultReflectorFactory();
		MetaClass mc = MetaClass.forClass(Student.class, rf);
		
		Assert.assertEquals("yuwen", mc.findProperty("yuwen"));
		Assert.assertEquals("age", mc.findProperty("age"));
	}
	
	/**
	 * Author是Blog的属性。
	 * mc.metaClassForProperty
	 */
	@Test
	public void test004metaClassForProperty(){
		ReflectorFactory rf = new DefaultReflectorFactory();
		MetaClass mc = MetaClass.forClass(Blog.class, rf);
		MetaClass mcc = mc.metaClassForProperty("author");
		Assert.assertTrue( mcc.hasGetter("username") );
	}
	
	
	/**
	 * MetaClass.forClass
	 */
	@Test
	public void test001hasGetter(){
		//Blog
		ReflectorFactory rf = new DefaultReflectorFactory();
		MetaClass mc = MetaClass.forClass(Blog.class, rf);
		Assert.assertTrue( mc.hasGetter("id") );
		Assert.assertTrue( mc.hasGetter("author.username") );
	}
	
	@Test
	public void test002getSetInvoker(){
		ReflectorFactory rf = new DefaultReflectorFactory();
		MetaClass mc = MetaClass.forClass(Blog.class, rf);
		Invoker invoker = mc.getSetInvoker("title");
		Blog blog = new Blog();
		try {
			invoker.invoke(blog, new Object[]{"Hello World!"});
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		Assert.assertEquals("Hello World!", blog.getTitle());
	}
	
	@Test
	public void test003getGetInvoker(){
		Blog blog = new Blog();
		blog.setTitle("Welcome!");
		
		ReflectorFactory rf = new DefaultReflectorFactory();
		MetaClass mc = MetaClass.forClass(Blog.class, rf);
		Invoker invoker = mc.getGetInvoker("title");
		
		Object ret = null;
		try {
			ret = invoker.invoke(blog, new Object[]{});
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		
		Assert.assertEquals("Welcome!", ret);
		
		try {
			ret = invoker.invoke(blog, null);
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		
		Assert.assertEquals("Welcome!", String.valueOf(ret) );
		
	}
	
	private static MetaClass metaclass = null; 
	
	/**
	 * java.lang.Exception: Method setup() should be static
	 */
//	@BeforeClass
//	public void setup(){
//		ReflectorFactory rf = new DefaultReflectorFactory();
//		metaclass = MetaClass.forClass(Blog.class, rf);
//	}
	
	@BeforeClass
	public static void setup(){
		ReflectorFactory rf = new DefaultReflectorFactory();
		metaclass = MetaClass.forClass(Blog.class, rf);
	}
	
}
